Skip to content

[REFACTOR][IR] Use PrimType for compiler dtypes#19875

Open
tqchen wants to merge 8 commits into
apache:mainfrom
tqchen:task-use-ty-primtype-for-source-of-dtype
Open

[REFACTOR][IR] Use PrimType for compiler dtypes#19875
tqchen wants to merge 8 commits into
apache:mainfrom
tqchen:task-use-ty-primtype-for-source-of-dtype

Conversation

@tqchen

@tqchen tqchen commented Jun 23, 2026

Copy link
Copy Markdown
Member

This PR removes the old runtime DataType wrapper as the compiler-facing dtype abstraction and routes dtype usage by boundary.

Rationale:

  • PrimType is the compiler IR type for primitive expressions, so using it as the dtype/type carrier unifies dtype information with Expr.ty.
  • This removes the need for a dedicated expression dtype path separate from type information.
  • Keeping dtype as an IR type leaves room for future expression type annotations without another parallel dtype abstraction.
  • Runtime, ABI, and dtype-valued attrs stay raw DLDataType, where a plain DLPack dtype value is the real boundary object.

Migration guide:

  • Use PrimType when code reasons about compiler expression types, tensor element compiler types, or constructs a PrimExpr/compiler type.
  • Use existing source types such as expr.ty(), ExprOp.expr_ty(), or TE tensor element dtype where possible instead of rebuilding a type from dtype text.
  • Use raw DLDataType for runtime constants, ABI paths, dtype-valued attrs, and storage/runtime helper logic.
  • Prefer direct PrimType equality, MatchesCode(...), MatchesElementType(...), and WithCode(...) over local wrappers or string dtype checks.
  • Keep public names such as GetDataType and output_dtype where they are API terminology, but align their value type with the compiler/runtime boundary.

Validation:

  • full branch changed-file pre-commit passed over 420 changed files
  • git diff --check passed
  • final grep found no PrimType::IsPredicate, .IsBool(, .IsInt(, .IsUInt(, removed type.cc helper names, or runtime/data_type.h references in checked paths
  • LLVM-enabled ninja -C build -j$(nproc) completed and linked lib/libtvm_compiler.so
  • focused Python pytest over TIRX ops/intrinsics, Relax qdq/manipulate legalizers, and contrib sort passed
  • direct TOPI smoke passed for touched math/scatter paths

The branch is intentionally stacked on #19874 (2bdedc93aa) so CI has the needed base fix.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the codebase to transition from using DataType to PrimType (backed by DLDataType), unifying the type system across IR dialects and improving type safety. The reviewer provided valuable feedback on leveraging the new PrimType APIs (such as bits(), lanes(), and IsScalableVector()) to avoid manual DLDataType unpacking and arithmetic, particularly in tensor allocation, memory view handling, static memory planning, and GPU code verification. Additionally, a bug was identified in src/relax/transform/utils.h where kDLBool was incorrectly checked against a bit width of 1 instead of the standard 8 bits.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/relax/transform/lower_alloc_tensor.cc
Comment thread src/relax/op/memory/view.cc
Comment thread src/relax/transform/static_plan_block_memory.cc Outdated
Comment thread src/relax/transform/utils.h Outdated
Comment thread src/s_tir/analysis/verify_gpu_code.cc Outdated
Comment thread src/s_tir/analysis/verify_gpu_code.cc
Comment thread src/s_tir/analysis/verify_gpu_code.cc Outdated
Comment thread src/s_tir/analysis/verify_gpu_code.cc Outdated
Comment thread src/s_tir/analysis/verify_gpu_code.cc Outdated
@tqchen tqchen force-pushed the task-use-ty-primtype-for-source-of-dtype branch 3 times, most recently from 3e75c55 to 74fba5e Compare June 23, 2026 16:32
@tqchen

tqchen commented Jun 23, 2026

Copy link
Copy Markdown
Member Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the TVM codebase by replacing the usage of tvm::DataType with tvm::PrimType and DLDataType across C++ and Python files to better align with DLPack. The code review feedback is highly consistent, recommending the use of the more idiomatic MatchesCode helper on PrimType instead of directly comparing raw data type codes (such as kDLFloat, kDLInt, and kDLBool). Additionally, it is suggested to simplify redundant checks by passing multiple type codes to a single variadic MatchesCode call.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/relax/op/tensor/index.cc Outdated
Comment thread src/relax/op/nn/nn.cc Outdated
Comment thread src/relax/op/nn/nn.cc Outdated
Comment thread src/relax/op/distributed/nn.cc Outdated
Comment thread src/relax/op/distributed/unary.h Outdated
Comment thread src/arith/transitive_comparison_analyzer.cc Outdated
Comment thread src/arith/int_constraints.cc Outdated
Comment thread src/arith/int_constraints.cc Outdated
Comment thread src/arith/int_set.cc Outdated
Comment thread src/arith/int_set.cc Outdated
@tqchen

tqchen commented Jun 23, 2026

Copy link
Copy Markdown
Member Author

/gemini Please run another review pass on latest head b8c7505. Since the last pass, I applied the Gemini MatchesCode cleanups, fixed the Python PrimType-to-runtime-dtype boundary in Relax gradient constants and TE NumPy test uses, reran full LLVM build plus focused Relax/TE/TIRX validation, and resolved the previous review threads that are addressed.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors TVM's type system by replacing the runtime-specific DataType with a unified compile-time PrimType (backed by DLDataType) across the compiler, runtime, and Python bindings. This extensive refactoring updates buffer declarations, expression nodes, and codegen backends to use PrimType or DLDataType directly. Feedback on the changes highlights a potential division-by-zero bug in Hexagon's GetVectorBytes for sub-byte types, a potential AttributeError in the Python PrimExpr.dtype property when self.ty is null or a pointer, and several opportunities to simplify type checks using the newly introduced IsScalar() helper and PrimType equality operators.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/backend/hexagon/codegen/llvm/codegen_hexagon.cc
Comment thread python/tvm/ir/expr.py Outdated
Comment thread include/tvm/topi/detail/broadcast.h Outdated
Comment on lines +61 to 63
auto cast_if_needed = [](PrimType to_type, PrimExpr expr) {
return to_type->dtype == expr.ty()->dtype ? expr : cast(to_type, expr);
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Since PrimType has operator== defined, the check to_type->dtype == expr.ty()->dtype can be simplified to to_type == expr.ty().

Suggested change
auto cast_if_needed = [](PrimType to_type, PrimExpr expr) {
return to_type->dtype == expr.ty()->dtype ? expr : cast(to_type, expr);
};
auto cast_if_needed = [](PrimType to_type, PrimExpr expr) {
return to_type == expr.ty() ? expr : cast(to_type, expr);
};

Comment thread src/arith/const_fold.h
Comment on lines +82 to +85
TVM_FFI_DCHECK(expr->BaseExprNode::ty.defined());
const auto* prim_ty = expr->BaseExprNode::ty.as<PrimTypeNode>();
TVM_FFI_DCHECK(prim_ty != nullptr);
return IsIndexType(prim_ty->dtype);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The manual checks on expr->BaseExprNode::ty are redundant because PrimExprNode::ty() already implements these checks and returns PrimType. We can simplify this to a single call to expr->ty().

Suggested change
TVM_FFI_DCHECK(expr->BaseExprNode::ty.defined());
const auto* prim_ty = expr->BaseExprNode::ty.as<PrimTypeNode>();
TVM_FFI_DCHECK(prim_ty != nullptr);
return IsIndexType(prim_ty->dtype);
return IsIndexType(expr->ty()->dtype);

Comment on lines 178 to +180

bool IsValidScalar(const PrimExpr& expr) const {
return expr.defined() && expr.dtype().is_scalar();
if (!expr.defined()) return false;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The check !ty.IsFixedLengthVector() && !ty.IsScalableVector() can be simplified using the IsScalar() helper method on PrimType.

    return expr.defined() && expr.ty().IsScalar();

@tqchen

tqchen commented Jun 23, 2026

Copy link
Copy Markdown
Member Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request performs a major refactoring of TVM's type system by removing the tvm::runtime::DataType wrapper class and replacing its usage with tvm::PrimType and raw DLDataType across the entire codebase, including TIR, Relax, TOPI, and various hardware backends (CUDA, Vulkan, Metal, WebGPU, Hexagon, and Trainium). PrimExpr and PrimExprNode now expose their types via PrimType (ty()) instead of DataType (dtype()), and corresponding Python bindings have been updated to reflect these changes. Since no review comments were provided, there is no specific feedback to address, and the changes appear to successfully unify and simplify the type representation.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

tqchen added 7 commits June 23, 2026 20:07
Use PrimType as the compiler-facing dtype/type carrier so primitive expression dtype information is unified with Expr.ty instead of flowing through a dedicated dtype path. This keeps compiler IR type information in the type system and leaves room for future expression type annotations.

Use raw DLDataType at runtime, ABI, storage-helper, and dtype-valued attr boundaries where a plain DLPack dtype value is the real interface. Keep the PrimType API minimal and hot-path friendly with value equality, matching helpers, documented factories, and cached common constructors.

Update TIRX, TE, TOPI, Relax, codegen, Python bindings, and tests to follow the compiler PrimType versus runtime DLDataType boundary.
@tqchen tqchen force-pushed the task-use-ty-primtype-for-source-of-dtype branch from b42ff43 to 35d4a00 Compare June 23, 2026 20:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant